﻿using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using DeepZoomPivotConstructor.VisualLib;
using IndicoInterface.SimpleAgendaDataModel;
using IndicoRender;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RenderEngine;
using RenderEngineInterfaces;

namespace t_IndicoRender
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class t_RenderIndicoMeeting
    {
        public t_RenderIndicoMeeting()
        {
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestInitialize]
        public void InitForTest()
        {
            t_TestingLibrary.Utilities.MyClassInit();
            t_TestingLibrary.Utilities.AddPart(new RenderControl());
            t_TestingLibrary.Utilities.AddPart(new LayoutHelper());
        }

        [Import]
        private IRenderEngine MyRender { get; set; }

        [TestCleanup]
        public void ShutDownTest()
        {
            t_TestingLibrary.Utilities.MyClassDone();
        }

        [TestMethod]
        public void TestCreate()
        {
            RenderIndicoMeeting m = new RenderIndicoMeeting();
        }

        [TestMethod]
        public void TestNullMeeting()
        {
            /// Nohting in the meeting - we render nohting!

            Meeting m = CreateBasicMeeting();
            m.Sessions = null;

            RenderIndicoMeeting mr = new RenderIndicoMeeting();
            Visual mvis = mr.Render(m).Result;
            Assert.IsNull(mvis, "Expected null rendering when meeting contains nothing!");
        }

        private static Meeting CreateBasicMeeting()
        {
            Meeting m = new Meeting()
            {
                EndDate = DateTime.Now,
                ID = "5",
                Site = "http://www.bogus.com",
                StartDate = DateTime.Now,
                Title = "hi title"
            };
            return m;
        }

        [Export(typeof(IRenderItem))]
        [RenderInfo(typeof(Session))]
        class RenderMeetingEmpty : IRenderItem
        {
            #region IRenderItem Members

            public System.Threading.Tasks.Task<Visual> Render(object what)
            {
                return null;
            }

            public RenderPluginPriority RenderPriority(object what)
            {
                return RenderPluginPriority.RPPGeneric;
            }

            #endregion
        }

        [TestMethod]
        public void TestSessionWithNoTalks()
        {
            Meeting m = new Meeting();
            Session s = new Session()
            {
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10",
                Title = "session"
            };
            m.Sessions = new Session[] { s };

            t_TestingLibrary.Utilities.AddPart(new RenderMeetingEmpty());
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            Visual v = rm.Render(m).Result;
            Assert.IsNull(v);
        }

        [Export(typeof(IRenderItem))]
        [RenderInfo(typeof(Session))]
        class RenderSessionSimple : IRenderItem
        {
            #region IRenderItem Members

            public double xSize = 1.0;
            public double ySize = 2.0;

            public Task<Visual> Render(object what)
            {
                return Task<Visual>.Factory.StartNew(() =>
                {
                    var vb = new VisualBitmapImage(xSize, ySize, 100, Color.Red);
                    Session s = what as Session;
                    vb.Info = new Visual.VisualInfo()
                    {
                        Title = s.Title,
                        Info = new string[] { "Starts and ends..." }
                    };
                    return vb;
                });
            }

            public RenderPluginPriority RenderPriority(object what)
            {
                return RenderPluginPriority.RPPGeneric;
            }

            #endregion
        }

        [TestMethod]
        public void TestOneSession()
        {
            Meeting m = CreateBasicMeeting();
            Session s = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            m.Sessions = new Session[] { s };

            t_TestingLibrary.Utilities.AddPart(new RenderSessionSimple());
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            Visual v = rm.Render(m).Result;
            Assert.IsNotNull(v, "Visual coming back from simple session should not be null!");
            Assert.AreEqual(string.Format("{0} - {1}", m.StartDate.ToString("yyyy-MM-dd"), m.Title), v.Info.Title, "Titles of the meeting and the main visual should be the same!");
            Assert.IsNotNull(v.Info.Info, "Info should not be null!");
            Assert.AreEqual(1, v.Info.Info.Length, "Expected 1 extra info dude");
            Assert.AreEqual(1, v.SGNodeList.Count, "Number of sg nodes was not correct!");
        }

        [TestMethod]
        public void TestBIGSession()
        {
            Meeting m = CreateBasicMeeting();
            Session s = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            m.Sessions = new Session[] { s };

            RenderSessionSimple rss = new RenderSessionSimple();
            rss.xSize = 20.0;
            rss.ySize = 30.0;
            t_TestingLibrary.Utilities.AddPart(rss);
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            Visual v = rm.Render(m).Result;
            Assert.IsTrue(v.Width < 11.0, "Width should be less than 11! (it was " + v.Width + ")");
        }

#if notyet
        /// Turn this on when we get this figured out - but there is a lot of data that needs to be
        /// passed around to get this to work internally!

        [TestMethod]
        public void TestSessionHotSpotLink()
        {
            Meeting m = CreateBasicMeeting();
            Session s = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            m.Sessions = new Session[] { s, s };

            t_TestingLibrary.Utilities.AddPart(new RenderSessionSimple());
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            var v = rm.RenderMeetingNow(m);
            Assert.IsNotNull(v, "expected a meeting to come back");

            var allHS = from vis in v.GetHierarchicalEnumerator(vis => (vis as VisualHotSpot) != null) where ((vis as VisualHotSpot) != null) select (VisualHotSpot) vis;
            Assert.IsTrue(allHS.Count() > 0, "We expect a few hot spots!");

            List<string> links = new List<string>();
            foreach (var hsvis in allHS)
            {
                hsvis.GetAllActoinData(hs =>
                    {
                        if (hs.LinkType == "uri")
                        {
                            links.Add(hs.LinkData);
                        }
                    });
            }

            Assert.IsTrue(links.Count > 0, "expected a link or more!");

            var sessLinks = from l in links where l.Contains("sessionId=10") select l;
            Assert.AreEqual(2, sessLinks.Count(), "Expected two links to session 10");
        }
#endif

        [TestMethod]
        public void TestMultipleSessions()
        {
            Meeting m = CreateBasicMeeting();
            Session s1 = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            Session s2 = new Session()
            {
                Title = "session title2",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "11"
            };
            m.Sessions = new Session[] { s1, s2 };

            t_TestingLibrary.Utilities.AddPart(new RenderSessionSimple());
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            Visual v = rm.Render(m).Result;

            Assert.IsNotNull(v, "Visual coming back from simple session should not be null!");
            //Assert.AreEqual(m.Title, v.Info.Title, "Titles of the meeting and the main visual should be the same!");
            Assert.IsNotNull(v.Info.Info, "Info should not be null!");
            Assert.AreEqual(1, v.Info.Info.Length, "Expected 1 extra info dude");
            Assert.AreEqual(4, v.SGNodeList.Count, "Number of sg nodes was not correct (2 for sessions, plus 2 for titles)!");
        }

        [TestMethod]
        public void TestMetaData()
        {
            Meeting m = CreateBasicMeeting();
            Session s = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            m.Sessions = new Session[] { s };

            t_TestingLibrary.Utilities.AddPart(new RenderSessionSimple());
            t_TestingLibrary.Utilities.AddPart(this);
            RenderIndicoMeeting rm = new RenderIndicoMeeting();
            t_TestingLibrary.Utilities.Compose(rm);

            Visual v = MyRender.Render(m);
            Assert.IsNotNull(v, "Visual coming back from simple session should not be null!");
        }

        [Export(typeof(IRenderItem))]
        [RenderInfo(typeof(Talk))]
        private class RenderTalkSimple : IRenderItem
        {
            public Task<Visual> Render(object what)
            {
                Talk t = what as Talk;
                Trace.WriteLine("Rendering talk with url " + t.SlideURL);
                return Task<Visual>.Factory.StartNew(() => new VisualBitmapImage(10, 10, 10, Color.Black) { Info = new Visual.VisualInfo() { Title = "basictitle", Info = new string[] { "line1" } } });
            }

            public RenderPluginPriority RenderPriority(object what)
            {
                return RenderPluginPriority.RPPGeneric;
            }
        }


        [TestMethod]
        public void TestRenderMeetingWithMaterial()
        {
            Meeting m = CreateBasicMeeting();
            Talk t1 = new Talk()
            {
                Title = "test1",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                SlideURL = null,
                SubTalks = new Talk[] { new Talk() { ID="1", SlideURL="http://www.nytimes.com/1", TalkType= TypeOfTalk.ExtraMaterial, StartDate=m.StartDate, EndDate=m.EndDate},
                    new Talk() { ID="1", SlideURL="http://www.nytimes.com/1", TalkType= TypeOfTalk.ExtraMaterial, StartDate=m.StartDate, EndDate=m.EndDate}}
            };
            m.MeetingTalks = new Talk[] { t1 };

            t_TestingLibrary.Utilities.AddPart(new RenderTalkSimple());
            t_TestingLibrary.Utilities.AddPart(this);
            t_TestingLibrary.Utilities.Compose(new RenderIndicoMeeting());

            Visual v = MyRender.Render(m);
            Assert.IsNotNull(v, "expecting rendered meeting");
            Assert.AreEqual(2, v.SGNodeList.Count(), "Expecting 2 talks and 2 backgrounds + a meeting background!");
        }

        [TestMethod]
        public void TestRenderMeetingWithMaterialAndSession()
        {
            Meeting m = CreateBasicMeeting();
            Talk t1 = new Talk()
            {
                Title = "test1",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                SlideURL = null,
                SubTalks = new Talk[] { new Talk() { ID="1", SlideURL="http://www.nytimes.com/1", TalkType= TypeOfTalk.ExtraMaterial, StartDate=m.StartDate, EndDate=m.EndDate},
                    new Talk() { ID="1", SlideURL="http://www.nytimes.com/1", TalkType= TypeOfTalk.ExtraMaterial, StartDate=m.StartDate, EndDate=m.EndDate}}
            };
            m.MeetingTalks = new Talk[] { t1 };
            Session s1 = new Session()
            {
                Title = "session title",
                StartDate = m.StartDate,
                EndDate = m.EndDate,
                ID = "10"
            };
            m.Sessions = new Session[] { s1 };

            t_TestingLibrary.Utilities.AddPart(new RenderTalkSimple());
            t_TestingLibrary.Utilities.AddPart(new RenderSessionSimple());
            t_TestingLibrary.Utilities.AddPart(this);
            t_TestingLibrary.Utilities.Compose(new RenderIndicoMeeting());

            Visual v = MyRender.Render(m);
            Assert.IsNotNull(v, "expecting rendered meeting");
            Assert.AreEqual(5, v.SGNodeList.Count(), "Expecting 2 talks and 2 backgrounds + a meeting background!");
        }
    }
}
